全メンバーアカウントにおける全リージョンのAWS IAM Access Analyzerを一括削除してみた
はじめに
クラスメソッドメンバーズのAWSアカウントをご利用の場合、セキュリティ強化とメンバーズサービス提供のため、複数のAWSサービスが自動的に有効化され、関連リソースが作成されます。
その一環として、cm-access-analyzer
という名前のAWS IAM Access Analyzerが自動的に全リージョンで作成されます。このAnalyzerの信頼ゾーンは、アカウント単位で設定されています。
以下の記事で解説されているように、マルチアカウント構成においては、通常、管理アカウントのみにAnalyzerを作成し、メンバーアカウントにはAnalyzerを作成しないケースが多いです。
このため、各メンバーアカウントの全リージョンに存在するcm-access-analyzer
を一括で削除する必要があります。本記事では、その効率的な方法をご紹介します。
実施手順の概要は以下の通りです。
- 管理アカウントに
AssumeMemberRole
というIAMロールを作成し、メンバーアカウントのCustomOrganizationAccessRole
を引き受ける権限を付与します。 - メンバーアカウントに
CustomOrganizationAccessRole
というIAMロールを作成し、IAM Access Analyzerの削除権限を付与します。
この作業は、管理アカウントからCloudFormation StackSetsを使用して各メンバーアカウントに一括展開します。 - 管理アカウントから単一のコマンドを実行し、特定のOrganizational Unit (OU)配下の全アカウント内の全リージョンにある
cm-access-analyzer
という名前のAnalyzerを削除します。
管理アカウントにIAMロール作成
まず、管理アカウントにIAMロールを作成し、メンバーアカウントのCustomOrganizationAccessRole
を引き受ける権限を付与します。
以下の操作は、AWS CloudShellを使用して実行します。
管理アカウントにAssumeMemberRole
というIAMロールを作成します。以下のAWS CLIコマンドを実行してください。
aws iam create-role --role-name AssumeMemberRole --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
次に、作成したロールに、メンバーアカウントのCustomOrganizationAccessRole
を引き受ける権限を付与します。CustomOrganizationAccessRole
については、後述します。
以下のコマンドを実行してください。
aws iam put-role-policy --role-name AssumeMemberRole --policy-name AssumeMemberRolePolicy --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::*:role/CustomOrganizationAccessRole"
}
]
}'
メンバーアカウントにIAMロール作成
次に、メンバーアカウントにIAMロールを作成します。
この作業は、管理アカウントからCloudFormation StackSetsを使用して、OU配下の全アカウントに一括で適用します。
以下のCloudFormationテンプレートを使用してください。
AWSTemplateFormatVersion: '2010-09-09'
Description: Create IAM Role for Access Analyzer management
Parameters:
ManagementAccountId:
Type: String
Description: "The AWS Account ID of the management account"
Resources:
CustomOrganizationAccessRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "CustomOrganizationAccessRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
AWS: !Sub "arn:aws:iam::${ManagementAccountId}:root"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "AccessAnalyzerPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "access-analyzer:CreateAnalyzer"
- "access-analyzer:DeleteAnalyzer"
- "access-analyzer:ListAnalyzers"
- "ec2:DescribeRegions"
Resource: "*"
- 管理アカウントのAWS マネジメントコンソールからCloudFormation StackSetsにアクセスし、上記のテンプレートをアップロードします。
- テンプレートのパラメータ設定画面で、「ManagementAccountId」に管理アカウントのAWSアカウントIDを入力します。
- その他の設定はデフォルトのまま、「次へ」をクリックして進みます。
- デプロイオプションの設定画面で、「アカウントを選択」ではなく「組織単位を選択」を選び、全メンバーアカウントを含むOUのOU IDを指定します。
- デプロイするリージョンとして、東京リージョン(ap-northeast-1)のみを選択します。メンバーアカウント数は2つなので、同時アカウントの最大数は2、障害耐性は1にします。
これで各メンバーアカウントにスタックが作成されます。
管理アカウントでアナライザー削除
AWS CloudShellでjq
コマンドラインツールをインストールします。以下のコマンドを実行してください。
sudo yum install -y jq
OU配下の全アカウントの全リージョンにおけるIAM Access Analyzerの存在を確認します。以下のコマンドを実行してください。
コマンド内のou-xxxx-xxxxxxxx
を実際のOU IDに置き換えてください。
ou_id="ou-xxxx-xxxxxxxx" && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
get_all_account_ids() {
local ou_id=$1
local accounts=$(aws organizations list-accounts-for-parent --parent-id $ou_id --query 'Accounts[*].Id' --output text)
local child_ous=$(aws organizations list-children --parent-id $ou_id --child-type ORGANIZATIONAL_UNIT --query 'Children[*].Id' --output text)
echo $accounts
for child_ou in $child_ous; do get_all_account_ids $child_ou; done
} && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name check-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
check_analyzers() {
local region=$1
local analyzers=$(aws accessanalyzer list-analyzers --region $region --query 'analyzers[*].{name:name,type:type}' --output json)
if [ "$(echo $analyzers | jq length)" -gt 0 ]; then
echo "$analyzers" | jq -r '.[] | "IAM Access Analyzer \"\(.name)\" (Type: \(.type)) exists in '"$region"' for account '"$account_id"'"'
else
echo "No IAM Access Analyzers exist in $region for account $account_id"
fi
} && \
member_accounts=$(get_all_account_ids $ou_id) && \
for account_id in $member_accounts; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
check_analyzers $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
//出力結果
Processing account: 012345678901
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in ap-south-1 for account 012345678901
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in eu-north-1 for account 012345678901
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in eu-west-3 for account 012345678901
~中略~
Processing account: 123456789012
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in ap-south-1 for account 123456789012
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in eu-north-1 for account 123456789012
IAM Access Analyzer "cm-access-analyzer" (Type: ACCOUNT) exists in eu-west-3 for account 123456789012
確認が完了したら、以下のコマンドを使用して、OU配下の全アカウントの全リージョンにあるcm-access-analyzer
という名前のIAM Access Analyzerを削除します。
コマンド内のou-xxxx-xxxxxxxx
を実際のOU IDに置き換えてください。
ou_id="ou-xxxx-xxxxxxxx" && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
analyzer_name='cm-access-analyzer' && \
get_all_account_ids() {
local ou_id=$1
local accounts=$(aws organizations list-accounts-for-parent --parent-id $ou_id --query 'Accounts[*].Id' --output text)
local child_ous=$(aws organizations list-children --parent-id $ou_id --child-type ORGANIZATIONAL_UNIT --query 'Children[*].Id' --output text)
echo $accounts
for child_ou in $child_ous; do get_all_account_ids $child_ou; done
} && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name delete-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
delete_analyzer() {
local region=$1
if aws accessanalyzer delete-analyzer --analyzer-name $analyzer_name --region $region >/dev/null 2>&1; then
echo "IAM Access Analyzer '$analyzer_name' deleted in $region for account $account_id"
else
echo "IAM Access Analyzer '$analyzer_name' not found or failed to delete in $region for account $account_id"
fi
} && \
member_accounts=$(get_all_account_ids $ou_id) && \
for account_id in $member_accounts; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
delete_analyzer $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
//出力結果
Processing account: 012345678901
IAM Access Analyzer 'cm-access-analyzer' deleted in ap-south-1 for account 012345678901
IAM Access Analyzer 'cm-access-analyzer' deleted in eu-north-1 for account 012345678901
IAM Access Analyzer 'cm-access-analyzer' deleted in eu-west-3 for account 012345678901
~省略~
コマンドが正常に実行されると、各アカウントの各リージョンでのAnalyzer削除結果が表示されます。すべての削除操作が成功したことを確認してください。先程の確認コマンドを再度実行してもよいです。
参考として、削除したAnalyzerを再作成する必要がある場合に備え、OU配下の全アカウントの全リージョンにIAM Access Analyzer cm-access-analyzer
を作成するコマンドを以下に示します。
ou_id="ou-xxxx-xxxxxxxx" && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
analyzer_name="cm-access-analyzer" && \
get_all_account_ids() {
local ou_id=$1
local accounts=$(aws organizations list-accounts-for-parent --parent-id $ou_id --query 'Accounts[*].Id' --output text)
local child_ous=$(aws organizations list-children --parent-id $ou_id --child-type ORGANIZATIONAL_UNIT --query 'Children[*].Id' --output text)
echo $accounts
for child_ou in $child_ous; do get_all_account_ids $child_ou; done
} && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name create-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
create_analyzer() {
local region=$1
if aws accessanalyzer create-analyzer --analyzer-name $analyzer_name --type ACCOUNT --region $region >/dev/null 2>&1; then
echo "IAM Access Analyzer '$analyzer_name' created in $region for account $account_id"
else
echo "IAM Access Analyzer '$analyzer_name' already exists or failed to create in $region for account $account_id"
fi
} && \
member_accounts=$(get_all_account_ids $ou_id) && \
for account_id in $member_accounts; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
create_analyzer $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
//出力結果
Processing account: 012345678901
IAM Access Analyzer 'cm-access-analyzer' created in ap-south-1 for account 012345678901
IAM Access Analyzer 'cm-access-analyzer' created in eu-north-1 for account 012345678901
IAM Access Analyzer 'cm-access-analyzer' created in eu-west-3 for account 012345678901
~省略~
アカウントIDを指定する
特定のアカウントのみでAnalyzerを削除または作成する必要がある場合、OU IDの代わりにアカウントIDを直接指定できます。
以下に、アカウントIDを使用してAnalyzerを確認と削除および作成するコマンドを示します。
以下のコマンドを使用して、指定したアカウントの全リージョンのAnalyzerを確認します。
member_accounts=("000000000000" "111111111111") && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name check-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
check_analyzers() {
local region=$1
local analyzers=$(aws accessanalyzer list-analyzers --region $region --query 'analyzers[*].{name:name,type:type}' --output json)
if [ "$(echo $analyzers | jq length)" -gt 0 ]; then
echo "$analyzers" | jq -r '.[] | "IAM Access Analyzer \"\(.name)\" (Type: \(.type)) exists in '"$region"' for account '"$account_id"'"'
else
echo "No IAM Access Analyzers exist in $region for account $account_id"
fi
} && \
for account_id in "${member_accounts[@]}"; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
check_analyzers $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
以下のコマンドを使用して、指定したアカウントの全リージョンのAnalyzerを削除します。
analyzer_name='cm-access-analyzer' && \
member_accounts=("000000000000" "111111111111") && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name delete-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
delete_analyzer() {
local region=$1
if aws accessanalyzer delete-analyzer --analyzer-name $analyzer_name --region $region >/dev/null 2>&1; then
echo "IAM Access Analyzer '$analyzer_name' deleted in $region for account $account_id"
else
echo "IAM Access Analyzer '$analyzer_name' not found or failed to delete in $region for account $account_id"
fi
} && \
for account_id in "${member_accounts[@]}"; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
delete_analyzer $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
削除したAnalyzerを再作成する必要がある場合、以下のコマンドを使用します。
analyzer_name='cm-access-analyzer' && \
member_accounts=("000000000000" "111111111111") && \
role_name="CustomOrganizationAccessRole" && \
regions=$(aws ec2 describe-regions --query Regions[*].RegionName --output text) && \
assume_role() {
local account_id=$1
local creds=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$role_name --role-session-name create-analyzer-session)
export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $creds | jq -r '.Credentials.SessionToken')
} && \
create_analyzer() {
local region=$1
if aws accessanalyzer create-analyzer --analyzer-name $analyzer_name --type ACCOUNT --region $region >/dev/null 2>&1; then
echo "IAM Access Analyzer '$analyzer_name' created in $region for account $account_id"
else
echo "IAM Access Analyzer '$analyzer_name' already exists or failed to create in $region for account $account_id"
fi
} && \
for account_id in "${member_accounts[@]}"; do
echo "Processing account: $account_id" && \
assume_role $account_id && \
for region in $regions; do
create_analyzer $region
done && \
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
done
今後発行されるメンバーアカウント
今後発行されるメンバーアカウントもアナライザーは作成された状態でアカウントを引き渡されます。
今後発行されるメンバーアカウントについても、アナライザーが作成された状態でアカウントが引き渡されます。
メンバーアカウント内で実行するため、CustomOrganizationAccessRole
は利用しません。
analyzer_name='cm-access-analyzer'
for r in $(aws ec2 describe-regions --query Regions[*].RegionName --output text)
do
aws accessanalyzer delete-analyzer --analyzer-name $analyzer_name --region $r
echo "Succeeded in delete IAM Access Analyzer@ $r"
done
作成する場合は以下のコマンドです。
analyzer_name='cm-access-analyzer'
for r in $(aws ec2 describe-regions --query Regions[*].RegionName --output text)
do
aws accessanalyzer delete-analyzer --analyzer-name $analyzer_name --region $r
echo "Succeeded in delete IAM Access Analyzer@ $r"
done
最後に
本記事では、AWS Organizations内の全メンバーアカウントにおける全リージョンのIAM Access Analyzerを一括で削除する方法について解説しました。
具体的には、以下の流れです。
- 管理アカウントでのIAMロールの作成
- CloudFormation StackSetsを使用した各メンバーアカウントでIAMロールを作成
- 一括削除のためのスクリプト実行
参考になれば幸いです。
参考